home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / pnm.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  419 lines

  1. /*
  2.  * $Id: pnm.c,v 0.91 1994/02/20 00:52:48 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  * PPM,PGM and PBM related stuff. For space reasons, the PBM is used as
  26.  * colormapped images.  All PNM should be transitional.
  27.  * BUGS: maximum 8-bits per channel
  28.  */
  29. #ifndef NO_PNM
  30.  
  31. #if !defined(lint) && defined(F_ID)
  32. char *id_ppm = "$Id: pnm.c,v 0.91 1994/02/20 00:52:48 zhao Pre-Release $";
  33. #endif
  34.  
  35. #include "bit.h"
  36. #include "dmalloc.h"
  37.  
  38. /********************* Local variables *****************************/
  39.  
  40. static int pgm;            /* pgm==1, PGM                 */
  41. static int raw = 1;        /* default writing             */
  42. static long pnm_rlines;        /* number of lines read so far */
  43. static int pnm_maxval;        /* input data PC resolution    */
  44. static float pnm_fnorm = 1.0;
  45.  
  46. /*******************************************************************
  47.  * Identify type and dimension
  48.  ******************************************************************/
  49.  
  50. int
  51. PNM_desc(IPTR p)
  52. {
  53.     char sig[4];
  54.     int err, pbm = 0;
  55.     FILE *fp = p->fp;
  56.  
  57.     if (Badfread(sig, 1, 2, fp))
  58.     return -1;
  59.  
  60.     /* this should never be true, but if it were, something is really wrong */
  61.  
  62.     if (sig[0] != 'P' || sig[1] < '1' || sig[1] > '6')
  63.       {
  64.       Bark("PPM_desc", "%s: Not a P{PGB}M file", p->ifile);
  65.       return -1;
  66.       }
  67.  
  68.     /*
  69.      * image dimension and type. If called thru im->desc, type is set
  70.      * automatically, but in case pnm_desc is called directly, need to take
  71.      * care of im->type here manually, ugly hack
  72.      */
  73.  
  74.     err = (p->w = readpint(fp)) <= 0 || (p->h = readpint(fp)) <= 0;
  75.  
  76.     if ((pgm = (sig[1] == '5' || sig[1] == '2')))
  77.     p->type = T_GRAY;
  78.     else if ((pbm = (sig[1] == '4' || sig[1] == '1')))
  79.     p->type = T_BW;
  80.     else
  81.     p->type = T_RGBA;
  82.  
  83.     raw = (sig[1] == '6' || sig[1] == '5' || sig[1] == '4');
  84.  
  85.  
  86.     err = err || (!pbm && ((pnm_maxval = readpint(fp)) <= 0));
  87.  
  88.     /* sanity check */
  89.     if (err)
  90.     return -1;
  91.  
  92.     if (!pbm && pnm_maxval > PCMAXV)
  93.       {
  94.       /*
  95.        * actually this can be relaxed a little: only RAW file can't be
  96.        * handled, the ASCII version is ok with a trivial normalization
  97.        */
  98.       Bark("PPM_desc", "%s: maxval>%d not supported", p->ifile, PCMAXV);
  99.       return -1;
  100.       }
  101.  
  102.     if (!pbm)
  103.       {
  104.       char pp_[50];
  105.       sprintf(pp_, "%s:maxval=%d", raw ? "Raw" : "Ascii", pnm_maxval);
  106.       set_iformat_info(p, pp_);
  107.       pnm_fnorm = (float) PCMAXV / pnm_maxval;
  108.       }
  109.     else
  110.       {
  111.       set_iformat_info(p, raw ? "Raw" : "Ascii");
  112.       p->colors = p->cmap->colors = 2;    /* fake a colormap */
  113.       }
  114.     return 0;
  115. }
  116.  
  117. /* ARGSUSED */
  118. static int
  119. PPM_getrow(FILE * fp, IPTR im, int row, pc_t *in)
  120. {
  121.     register pc_t *rgb = in, *rend = rgb + 3 * im->w;
  122.     register int err, r, g, b;
  123.  
  124.     if (raw)
  125.       {
  126.       err = Badfread(rgb, 1, (size_t) 3 * im->w, fp);
  127.       }
  128.     else
  129.       {
  130.       for (err = 0; rgb < rend && !err;)
  131.         {
  132.         if ((r = readpint(fp)) >= 0 &&
  133.             (g = readpint(fp)) >= 0 &&
  134.             (b = readpint(fp)) >= 0)
  135.           {
  136.               *rgb++ = r;
  137.               *rgb++ = g;
  138.               *rgb++ = b;
  139.           }
  140.         else
  141.             err = 1;
  142.         }
  143.       }
  144.  
  145.     if (err)
  146.       {
  147.       Bark("PPM_getrow", "%s: Junk found", im->ifile);
  148.       return -1;
  149.       }
  150.  
  151.     if (pnm_maxval != PCMAXV && pnm_fnorm > 1.1)
  152.       {
  153.       for (rgb = in; rgb < rend;)
  154.         {
  155.         *rgb++ = (pnm_fnorm * (*in++));
  156.         *rgb++ = (pnm_fnorm * (*in++));
  157.         *rgb++ = (pnm_fnorm * (*in++));
  158.         }
  159.       }
  160.     return 0;
  161. }
  162.  
  163. /* ARGSUSED */
  164. static int
  165. PGM_getrow(FILE * fp, IPTR p, int row, pc_t *in)
  166. {
  167.     register pc_t *rgb = in, *rend = rgb + p->w;
  168.     register int err = 0, r;
  169.  
  170.     if (raw)
  171.       {
  172.       err = Badfread(rgb, 1, p->w, fp);
  173.       }
  174.     else
  175.       {
  176.       for (; !err && rgb < rend; rgb++)
  177.         {
  178.         err = ((r = readpint(fp)) < 0);
  179.         *rgb = r;
  180.         }
  181.       }
  182.  
  183.     if (err)
  184.       {
  185.       Bark("PGM_getrow", "Junk in pixel area");
  186.       return -1;
  187.       }
  188.  
  189.     if (pnm_maxval != PCMAXV && pnm_fnorm > 1.1)
  190.       {
  191.       for (rgb = in; rgb < rend; rgb++)
  192.           *rgb = (pnm_fnorm * (*in++));
  193.       }
  194.     return 0;
  195. }
  196.  
  197. int
  198. PPM_load(IPTR im)
  199. {
  200.     register rgba_t *rgba, *rend;
  201.     register int j;
  202.     int err = 0, h = im->h;
  203.     pc_t *tmp, *head;
  204.     FILE *fp = im->fp;
  205.  
  206.     pnm_rlines = progress_report(pgm ? "Loading PGM ..." :
  207.                  "Loading PPM ...", h);
  208.     if (!(tmp = head = malloc(sizeof(*tmp) * 3 * im->w)))
  209.     return -1;
  210.  
  211.     /*
  212.      * get one row at a time and when errors occurs,  try not to abort
  213.      * completely by returning number of lines read
  214.      */
  215.  
  216.     for (j = 0; j < h && !err; j++)
  217.       {
  218.       REPORT(j, pnm_rlines);
  219.       rgba = ((rgba_t **) im->mraster)[h - 1 - j];
  220.       rend = rgba + im->w;
  221.  
  222.       err = (pgm ? PGM_getrow : PPM_getrow) (fp, im, j, head);
  223.       if (pgm)
  224.         {
  225.         for (tmp = head; rgba < rend; rgba++, tmp++)
  226.             *rgba = Pack(*tmp, *tmp, *tmp);
  227.         }
  228.       else
  229.         {
  230.         for (tmp = head; rgba < rend; rgba++, tmp += 3)
  231.             *rgba = Pack(*tmp, *(tmp + 1), *(tmp + 2));
  232.         }
  233.       }
  234.     free(head);
  235.     remove_progress_report();
  236.     return j;
  237. }
  238.  
  239. int
  240. PBM_load(IPTR im)
  241. {
  242.     register bw_t *ci, *cend;
  243.     register int j, bit, k;
  244.     int w = im->w, h = im->h;
  245.     FILE *fp = im->fp;
  246.     int err;
  247.  
  248.     /* fake a colormap with 2 entries in it: 0 white, 1 black */
  249.     im->cmap->ct[0][0] = im->cmap->ct[1][0] = im->cmap->ct[2][0] = PCMAXV;
  250.     im->cmap->ct[0][1] = im->cmap->ct[1][1] = im->cmap->ct[2][1] = 0;
  251.  
  252.     im->colors = im->cmap->colors = 2;    /* fake a colormap */
  253.  
  254.     pnm_rlines = progress_report("Loading PBM ...", h);
  255.  
  256.     for (j = err = 0; j < h; j++)
  257.       {
  258.       REPORT(j, pnm_rlines);
  259.       ci = ((bw_t **) im->mraster)[h - 1 - j];
  260.       cend = ci + w;
  261.       if (!raw)
  262.         {
  263.         for (; ci < cend; ci++)
  264.             *ci = (readpint(fp) > 0);
  265.         err = feof(fp);
  266.         }
  267.       else
  268.         {
  269.         for (bit = 0, k = 0; !err && ci < cend; ci++, bit++)
  270.           {
  271.               if (!(bit &= 7))
  272.               k = getc(fp);
  273.               err = k == EOF;
  274.               *ci = (k & 0x80) ? 1 : 0;
  275.               k <<= 1;
  276.           }
  277.         }
  278.       }
  279.  
  280. #ifdef MDEBUG
  281.     M_debug("PBM_load", "Returning j=%d", j);
  282. #endif
  283.  
  284.     remove_progress_report();
  285.     return j;
  286. }
  287.  
  288. int
  289. PBM_dump(IPTR im)
  290. {
  291.     register bw_t *ci, *cend;
  292.     register int j, k, bit;
  293.     int w = im->w, h = im->h;
  294.     FILE *fp = im->fp;
  295.  
  296.     pnm_rlines = progress_report("Writing PBM...", h);
  297.     fprintf(fp, "%s\n%d %d\n", raw ? "P4" : "P1", w, h);
  298.  
  299.     for (j = 0, k = 1; j < h; j++)
  300.       {
  301.       REPORT(j, pnm_rlines);
  302.       cend = (ci = ((bw_t **) im->mraster)[h - 1 - j]) + w;
  303.       if (!raw)
  304.         {
  305.         for (; ci < cend; ci++, k++)
  306.           {
  307.               fputs(*ci ? "1 " : "0 ", fp);
  308.               if ((k % 34) == 0)
  309.               putc('\n', fp);
  310.           }
  311.         }
  312.       else
  313.         {
  314.         for (bit = 0, k = 0; ci < cend; ci++)
  315.           {
  316.               k = (k << 1) | *ci;
  317.               if (++bit == 8)
  318.             {
  319.                 putc(k, fp);
  320.                 bit = k = 0;
  321.             }
  322.           }
  323.         if (bit)
  324.           {
  325.               k <<= (8 - bit);
  326.               putc(k, fp);
  327.           }
  328.         }
  329.       }
  330.     if (!raw)
  331.     putc('\n', fp);
  332.     remove_progress_report();
  333.     return (fflush(fp)) ? -1 : 0;
  334. }
  335.  
  336. int
  337. PPM_dump(IPTR im)
  338. {
  339.     register rgba_t *rgba, *rend;
  340.     register int r, g, b;
  341.     register int j, k;
  342.     int w = im->w, h = im->h;
  343.     const char *s;
  344.     FILE *fp = im->fp;
  345.  
  346.     pgm = (im->type == T_GRAY);
  347.     pnm_rlines = progress_report(pgm ? "Writing PGM..." : "Writing PPM...", h);
  348.     s = pgm ? (raw ? "P5" : "P2") : (raw ? "P6" : "P3");
  349.     fprintf(fp, "%s\n%d %d\n%d\n", s, w, h, PCMAXV);
  350.  
  351.     for (j = 0, k = 1; j < h; j++)
  352.       {
  353.       REPORT(j, pnm_rlines);
  354.       rend = (rgba = ((rgba_t **) im->mraster)[h - 1 - j]) + w;
  355.       if (pgm)
  356.         {
  357.         for (; rgba < rend; rgba++, k++)
  358.           {
  359.               r = (*rgba) & PCMAXV;
  360.               if (!raw)
  361.             {
  362.                 fprintf(fp, "% 3d", r);
  363.                 if ((k % 17) == 0)
  364.                 putc('\n', fp);
  365.             }
  366.               else
  367.               putc(r, fp);
  368.           }
  369.         }
  370.       else
  371.         {
  372.         for (; rgba < rend; rgba++, k++)
  373.           {
  374.               CPACK2RGB(*rgba, r, g, b);
  375.               if (raw)
  376.             {
  377.                 putc(r, fp);
  378.                 putc(g, fp);
  379.                 putc(b, fp);
  380.             }
  381.               else
  382.             {
  383.                 fprintf(fp, "%4d%4d%4d ", r, g, b);
  384.                 if ((k % 5) == 0)
  385.                 putc('\n', fp);
  386.             }
  387.           }
  388.         }
  389.       }
  390.     if (!raw)
  391.     putc('\n', fp);
  392.     remove_progress_report();
  393.  
  394.     return (fflush(fp)) ? -1 : im->h;
  395. }
  396.  
  397. /* ARGSUSED */
  398. const char *
  399. PPM_wdefault(const IPTR im)
  400. {
  401.     return raw ? "Raw" : "Ascii";
  402. }
  403.  
  404. /* utility function for setting raw output */
  405. void
  406. set_pnm_raw(int y)
  407. {
  408.     raw = y;
  409. }
  410.  
  411. /* ARGSUSED */
  412. int
  413. PPMdump_init(IPTR im)
  414. {
  415.     return (raw = !raw);
  416. }
  417.  
  418. #endif
  419.